package com.lonely.goods.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.goods.domain.dto.material.MaterialSubmitDTO;
import com.lonely.goods.domain.dto.material.QueryMaterialPageDTO;
import com.lonely.goods.domain.entity.SysMaterial;
import com.lonely.goods.domain.entity.SysMaterialItem;
import com.lonely.goods.domain.vo.material.page.MaterialDetailVO;
import com.lonely.goods.domain.vo.material.page.MaterialItemDetailVO;
import com.lonely.goods.domain.vo.material.page.MaterialPageQueryVO;
import com.lonely.goods.mapper.SysMaterialMapper;
import com.lonely.goods.service.IMaterialItemService;
import com.lonely.goods.service.IMaterialLogService;
import com.lonely.goods.service.IMaterialService;
import com.lonely.order.utils.GeneratorUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/7/2 10:43
 * @description: 物料接口实现
 */
@Service
public class MaterialServiceImpl extends ServiceImpl<SysMaterialMapper, SysMaterial> implements IMaterialService {

    @Autowired
    private IMaterialItemService materialItemService;

    @Autowired
    private IMaterialLogService materialLogService;

    /**
     * 分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<MaterialPageQueryVO> page(QueryMaterialPageDTO queryDto) {
        Page<MaterialPageQueryVO> page = new Page<>(queryDto.getCurrent(), queryDto.getSize());
        page = super.getBaseMapper().page(page, queryDto);
        return page;
    }


    /**
     * 启用物料
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enabled(Long id) {
        SysMaterial material = super.getById(id);
        Assert.notNull(material, "该物料不存在");
        material.setStatus(CommonStatus.ENABLE.code);
        super.updateById(material);

        // 添加操作日志
        this.materialLogService.addLog(material.getId(), "启用物料信息", SecurityUtils.getUsername());
    }

    /**
     * 禁用物料
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disable(Long id) {
        SysMaterial sysSupplier = super.getById(id);
        Assert.notNull(sysSupplier, "该物料不存在");
        sysSupplier.setStatus(CommonStatus.DISABLE.code);
        super.updateById(sysSupplier);

        // 添加操作日志
        this.materialLogService.addLog(sysSupplier.getId(), "禁用物料信息", SecurityUtils.getUsername());
    }

    /**
     * 获取指定物料id对应的物料详情
     *
     * @param materialId
     * @return
     */
    @Override
    public MaterialDetailVO detail(Long materialId) {
        SysMaterial sysMaterial = super.getById(materialId);
        Assert.notNull(sysMaterial, "该物料不存在");

        MaterialDetailVO materialDetailVO = new MaterialDetailVO();
        BeanUtils.copyProperties(sysMaterial, materialDetailVO);
        materialDetailVO.setMaterialItems(this.materialItemService.list(new LambdaQueryWrapper<SysMaterialItem>()
                .eq(SysMaterialItem::getMaterialId, materialId)
        ).stream().map(x -> {
            MaterialItemDetailVO materialItemVO = new MaterialItemDetailVO();
            BeanUtils.copyProperties(x, materialItemVO);
            return materialItemVO;
        }).collect(Collectors.toList()));

        return materialDetailVO;
    }

    /**
     * 保存/编辑 物料信息
     *
     * @param submitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(MaterialSubmitDTO submitDto) {
        // 处理物料信息
        SysMaterial material;
        if (submitDto.getId() == null) {
            material = this.createMaterial(submitDto);
        } else {
            material = this.editMaterial(submitDto);
        }

        // 处理物料明细信息
        this.materialItemService.submitMaterialItems(material.getId(), submitDto.getMaterialItems());
    }

    /**
     * 创建物料
     *
     * @param submitDto
     */
    private SysMaterial createMaterial(MaterialSubmitDTO submitDto) {
        Assert.isNull(submitDto.getId(), "参数错误(id)");
        checkMaterial(submitDto);

        SysMaterial sysMaterial = new SysMaterial();
        BeanUtils.copyProperties(submitDto, sysMaterial);
        sysMaterial.setSpu(GeneratorUtil.generatorMaterialSpu());
        sysMaterial.setFactoryId(SecurityUtils.getFactoryId());
        sysMaterial.setCreateBy(SecurityUtils.getUserId());
        sysMaterial.setUpdateBy(SecurityUtils.getUserId());
        super.save(sysMaterial);

        // 添加操作日志
        this.materialLogService.addLog(sysMaterial.getId(), "创建物料信息", SecurityUtils.getUsername());

        return sysMaterial;
    }

    /**
     * 编辑物料
     *
     * @param submitDto
     */
    private SysMaterial editMaterial(MaterialSubmitDTO submitDto) {
        Assert.notNull(submitDto.getId(), "参数错误(id)");
        checkMaterial(submitDto);
        SysMaterial oldMaterial = super.getById(submitDto.getId());
        BeanUtils.copyProperties(submitDto, oldMaterial);
        oldMaterial.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(oldMaterial);

        // 添加操作日志
        this.materialLogService.addLog(oldMaterial.getId(), "修改物料信息", SecurityUtils.getUsername());

        return oldMaterial;
    }

    /**
     * 校验物料信息
     *
     * @param submitDto
     */
    private void checkMaterial(MaterialSubmitDTO submitDto) {

        // 1. 校验物料sku是否重复
        int count = super.count(new LambdaQueryWrapper<SysMaterial>()
                .eq(SysMaterial::getSpu, submitDto.getSpu())
                .ne(submitDto.getId() != null, SysMaterial::getId, submitDto.getId()));
        Assert.isTrue(count == 0, "该SKU已存在");

        //2. 校验物料id是否正确
        if (submitDto.getId() != null) {
            SysMaterial material = super.getById(submitDto.getId());
            Assert.notNull(material, "该物料不存在");
        }
    }
}
